package com.shop.cereshop.app.service.recommend.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.shop.cereshop.app.dao.recommend.CereRecommendTrendsDAO;
import com.shop.cereshop.app.dao.recommend.CereRecommendTypeDAO;
import com.shop.cereshop.app.dao.recommend.CereRecommendTypeRelationDAO;
import com.shop.cereshop.app.page.recommend.CereRecommendTypeVO;
import com.shop.cereshop.app.page.recommend.RecommendPageVO;
import com.shop.cereshop.app.page.recommend.RecommendType;
import com.shop.cereshop.app.page.recommend.RecommendTypeVO;
import com.shop.cereshop.app.param.recommend.RecommendPageDTO;
import com.shop.cereshop.app.param.recommend.RecommendTypeDTO;
import com.shop.cereshop.app.service.recommend.CereRecommendTypeService;
import com.shop.cereshop.commons.domain.buyer.CereBuyerUser;
import com.shop.cereshop.commons.domain.common.Page;
import com.shop.cereshop.commons.domain.recommend.CereRecommendType;
import com.shop.cereshop.commons.enums.RedisEnum;
import com.shop.cereshop.commons.exception.CoBusinessException;
import com.shop.cereshop.commons.utils.EmptyUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CereRecommendTypeServiceImpl implements CereRecommendTypeService {

    @Autowired
    private CereRecommendTypeDAO cereRecommendTypeDAO;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private CereRecommendTrendsDAO cereRecommendTrendsDAO;

    @Autowired
    private CereRecommendTypeRelationDAO cereRecommendTypeRelationDAO;

    @Override
    public List<CereRecommendTypeVO> getAll() {
        return cereRecommendTypeDAO.getAll();
    }

    @Override
    public Page<RecommendTypeVO> getRecommendTypeVOs(RecommendPageDTO param) {
        return null;
    }

    @Override
    public List<RecommendType> getRecommendTypes() {
        return cereRecommendTypeDAO.getRecommendTypes();
    }

    @Override
    public List<Long> getRecommendTypeIds() {
        return cereRecommendTypeDAO.getRecommendTypeIds();
    }

    @Override
    public RecommendTypeVO getRecommendType(Long typeId) {
        return cereRecommendTypeDAO.getRecommendType(typeId);
    }

    @Override
    @Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, rollbackFor = {CoBusinessException.class, Exception.class})
    public int addRecommendType(CereRecommendType param) {
        return cereRecommendTypeDAO.insert(param);
    }

    @Override
    public List<RecommendTypeVO> getHotRecommendType(RecommendTypeDTO param, CereBuyerUser user) {
        //封装分页参数
        int page = param.getPage();
        int pageSize = param.getPageSize();
        int start = (page - 1) * pageSize;
        int end = start + pageSize - 1;

        //redis中获取话题热度
        Set<ZSetOperations.TypedTuple<String>> set = redisTemplate.opsForZSet().reverseRangeWithScores(RedisEnum.RECOMMEND_TYPE_TOP.getKey(), start, end);

        log.info("从Redis获取话题热度排行，范围: {}-{}, 结果数量: {}", start, end, set != null ? set.size() : 0);

        //如果排行榜为空，直接走数据库
        if (EmptyUtils.isEmpty(set)) {
            log.info("Redis中没有话题热度数据，走数据库查询");
            //封装分页参数
            PageHelper.startPage(param.getPage(), param.getPageSize());
            List<RecommendTypeVO> recommendTypeVOS = cereRecommendTypeDAO.getRecommendTypeVOS(param);
            //根据话题列表id填补动态数据
            recommendTypeVOS = this.getRecommendPageVO(recommendTypeVOS, user);
            return recommendTypeVOS;
        }

        //将set集合的value转换为list集合
        List<String> list = new ArrayList<>();
        for (ZSetOperations.TypedTuple<String> tuple : set) {
            list.add(tuple.getValue());
        }

        //redis中获取话题数据
        List<RecommendTypeVO> recommendTypes = redisTemplate.opsForHash().multiGet(RedisEnum.RECOMMEND_TYPE.getKey(), list);

        log.info("从Redis获取话题详情，ID列表: {}, 结果数量: {}", list, recommendTypes != null ? recommendTypes.size() : 0);

        //检查是否有缺失数据
        boolean hasMissData = recommendTypes.stream().anyMatch(Objects::isNull);

        if (hasMissData) {
            log.info("Redis中存在缺失的话题数据");
        }

        //如果redis没有有效数据走数据库
        if (EmptyUtils.isEmpty(recommendTypes) || hasMissData) {
            log.info("Redis中没有有效的话题数据，走数据库查询");
            //封装分页参数
            PageHelper.startPage(param.getPage(), param.getPageSize());
            List<RecommendTypeVO> recommendTypeVOS = cereRecommendTypeDAO.getRecommendTypeVOS(param);
            //根据话题列表id填补动态数据
            recommendTypeVOS = this.getRecommendPageVO(recommendTypeVOS, user);
            return recommendTypeVOS;
        }

        //过滤掉空数据
        recommendTypes = recommendTypes.stream()
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        log.info("成功从Redis获取话题数据，开始获取话题下的动态数据");

        //为每个话题填充对应的4个热门动态
        for (RecommendTypeVO recommendType : recommendTypes) {
            Long typeId = recommendType.getRecommendTypeId();
            String typeTrendsKey = RedisEnum.RECOMMEND_TRENDS.getKey() + ":" + typeId;

            // 从Redis中获取该话题下的前4个热门动态
            Set<ZSetOperations.TypedTuple<String>> trendSet = redisTemplate.opsForZSet()
                    .reverseRangeWithScores(RedisEnum.RECOMMEND_TYPE_HOT_TRENDS.getKey() + ":" + typeId, 0, 3);

            log.info("从Redis获取话题{}的动态热度排行，结果数量: {}", typeId, trendSet != null ? trendSet.size() : 0);

            List<RecommendPageVO> recommendPageVOs = new ArrayList<>();
            if (CollUtil.isNotEmpty(trendSet)) {
                // 提取动态ID
                List<String> trendIds = trendSet.stream()
                        .map(ZSetOperations.TypedTuple::getValue)
                        .collect(Collectors.toList());

                log.info("从Redis获取话题{}的动态详情，ID列表: {}", typeId, trendIds);

                // 批量获取动态详情
                List<RecommendPageVO> trends = redisTemplate.opsForHash().multiGet(typeTrendsKey, trendIds);

                // 过滤掉空值并添加到结果列表
                recommendPageVOs = trends.stream()
                        .filter(Objects::nonNull)
                        .collect(Collectors.toList());

                log.info("成功获取话题{}的动态详情，有效数量: {}", typeId, recommendPageVOs.size());
            }

            recommendType.setRecommendPageVOs(recommendPageVOs);
        }

        log.info("成功从Redis获取所有话题及动态数据，话题数量: {}", recommendTypes.size());
        return recommendTypes;
    }

    @Override
    public Page<RecommendTypeVO> getRecommendTypePage(RecommendPageDTO param, CereBuyerUser user) {
//        //封装分页参数
//        int page = param.getPage();
//        int pageSize = param.getPageSize();
//        int start = (page - 1) * pageSize;
//        int end = start + pageSize - 1;
//
//        //redis中获取话题热度
//        Set<ZSetOperations.TypedTuple<String>> set = redisTemplate.opsForZSet().reverseRangeWithScores(RedisEnum.RECOMMEND_TYPE_TOP.getKey(), start, end);
//
//        //如果redis的数据为空，且数据个数不足，直接走数据库
//        //检查是否有确实数据
//        boolean hasMissData = set.stream().anyMatch(Objects::isNull);
//        if (EmptyUtils.isEmpty(set) || hasMissData) {
            //封装分页参数
//            if (param.getFilter() == 5) {
//                param.setBuyerUserId(user.getBuyerUserId());
//                PageHelper.startPage(param.getPage(), param.getPageSize());
//                List<RecommendTypeVO> recommendTypeVOs = cereRecommendTypeDAO.getRecommendTypeVOS(param);
//
//                // 为话题填充热门动态列表
//                recommendTypeVOs = this.getRecommendPage(recommendTypeVOs, param, user);
//                PageInfo<RecommendTypeVO> pageInfo = new PageInfo<>(recommendTypeVOs);
//                Page<RecommendTypeVO> result = new Page(pageInfo.getList(), pageInfo.getTotal());
//                return result;
//            }
//        }
//
//        //将set集合的value转换为list集合
//        List<String> list = set.stream().map(ZSetOperations.TypedTuple::getValue).collect(Collectors.toList());
//
//        //redis中获取话题数据
//        List<RecommendTypeVO> recommendTypes = redisTemplate.opsForHash().multiGet(RedisEnum.RECOMMEND_TYPE.getKey(), list);
//
//        //检查是否有确实数据
//        boolean hasMissedData = recommendTypes.stream().anyMatch(Objects::isNull);
//
//        //如果redis没有有效数据走数据库
//        if (EmptyUtils.isEmpty(recommendTypes) || hasMissedData) {
//            //封装分页参数
//            PageHelper.startPage(param.getPage(), param.getPageSize());
//            List<RecommendTypeVO> recommendTypeVOs = cereRecommendTypeDAO.getRecommendTypeVOS(param);
//            // 为话题填充热门动态列表
//            recommendTypeVOs = this.getRecommendPage(recommendTypeVOs, param, user);
//            PageInfo<RecommendTypeVO> pageInfo = new PageInfo<>(recommendTypeVOs);
//            Page<RecommendTypeVO> result = new Page(pageInfo.getList(), pageInfo.getTotal());
//            return result;
//        } else {
//            //redis中有数据,为话题填充热门动态列表
//            recommendTypes = this.getRecommendPage(recommendTypes, param,  user);
//            Page<RecommendTypeVO> data = new Page(recommendTypes, recommendTypes.size());
//            return data;
//        }
        return new Page<> (Collections.emptyList(), 0);
    }

    public List<RecommendTypeVO> getRecommendPageVO(List<RecommendTypeVO> recommendTypes, CereBuyerUser user) {
        //根据话题id获取话题下的动态列表
        if (EmptyUtils.isEmpty(recommendTypes)) {
            //如果recommendTypes集合为空，直接返回一个空的List集合
            return new ArrayList<>();
        }
        //将集合的recommendTypeId属性转换为List集合
        List<Long> recommendTypeIds = recommendTypes.stream()
                .map(RecommendTypeVO::getRecommendTypeId)
                .collect(Collectors.toList());

        //批量查询动态数据
        if (CollUtil.isNotEmpty(recommendTypeIds)) {
            //获取动态列表数据
            List<RecommendPageVO> cereRecommendPageVOS = cereRecommendTypeDAO.getRecommendTypeVO(recommendTypeIds, user.getBuyerUserId());
            //根据hashmap集合和cereRecommendPageVOS集合，根据cereRecommendPageVOS集合每个对象的currenttypeid填充对应的话题id到recommendTypes集合的recommendPageVOs属性
            if (CollUtil.isNotEmpty(cereRecommendPageVOS)) {
                // 按currentTypeId分组
                Map<Long, List<RecommendPageVO>> groupedByType = cereRecommendPageVOS.stream()
                        .filter(pageVO -> pageVO.getCurrentTypeId() != null)
                        .collect(Collectors.groupingBy(RecommendPageVO::getCurrentTypeId));

                // 将分组后的动态列表设置到对应的话题类型中
                for (RecommendTypeVO recommendTypeVO : recommendTypes) {
                    Long typeId = recommendTypeVO.getRecommendTypeId();
                    if (typeId != null) {
                        List<RecommendPageVO> pageVOs = groupedByType.getOrDefault(typeId, new ArrayList<>());
                        // 限制每个话题下最多4个动态
                        if (pageVOs.size() > 4) {
                            pageVOs = pageVOs.subList(0, 4);
                        }
                        recommendTypeVO.setRecommendPageVOs(pageVOs);
                    } else {
                        recommendTypeVO.setRecommendPageVOs(new ArrayList<>());
                    }
                }
            } else {
                // 如果没有查询到动态，给每个话题设置空列表
                for (RecommendTypeVO recommendTypeVO : recommendTypes) {
                    recommendTypeVO.setRecommendPageVOs(new ArrayList<>());
                }
            }

        }
        return recommendTypes;
    }
}
